package com.neuronrobotics.replicator.gui.preview.controller;

import java.util.Arrays;
import java.util.Iterator;

import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import android.util.Log;

import com.neuronrobotics.replicator.gui.preview.model.STLWorkspaceModel;
import com.neuronrobotics.replicator.gui.preview.view.STLWorkspaceView;
import com.neuronrobotics.replicator.gui.stl.GeneralTransform3D.MatrixOrder;
import com.neuronrobotics.replicator.gui.stl.STLObject;
import com.neuronrobotics.replicator.gui.stl.STLWorkspaceObject;

public abstract class DefaultSTLPreviewController {
	
	protected GeneralSTLTransformHelper theTransformHelper;
	protected GeneralCameraController theCameraController;
	protected STLPreviewMouseController theMouseController;
	protected STLWorkspaceView theWorkspaceView;
	protected STLWorkspaceModel theWorkspaceModel;
		
	public DefaultSTLPreviewController(){
	}
	
	public STLPreviewMouseController getSTLPreviewMouseController(){
		return this.theMouseController;
	}
	
	public GeneralCameraController getGeneralCameraController(){
		return this.theCameraController;
	}
	
	public GeneralSTLTransformHelper getGeneralSTLTransformHelper(){
		return this.theTransformHelper;
	}
	
	public boolean placeAllObjectsOnWorkspace(){
		
		STLWorkspaceObject theWSO= theWorkspaceModel.getWorkspaceObject();
		if(theWSO==null) return false;
		
		float surfaceY = theWSO.getSurfaceY();
		//Log.d("POW","Surface y: "+surfaceY);
		
		Iterator<STLObject> theBaseObjects = theWorkspaceModel.getBaseSTLObjectIterator();
		float[] currMins = new float[3];
		while(theBaseObjects.hasNext()){
			STLObject currObj = theBaseObjects.next();
			theWorkspaceModel.getCurrMins(currObj, currMins);
			Log.d("POW","Current Mins:" +Arrays.toString(currMins));
			float yTrans = surfaceY - currMins[1];
			//Log.d("POW","Y Translation:" +yTrans);
			float[] mat4 = new float[16];
			theWorkspaceModel.getTransformMatrix(currObj, mat4, MatrixOrder.ROW_MAJOR);
			//Log.d("POW","Current Transform: " + Arrays.toString(mat4));
			
			Matrix4f currMat = new Matrix4f(mat4);
			
			//This is pretty ridic but it works
			//so i'll make it less dumb later
			Point3f quickFix = new Point3f(0,0,0);
			currMat.transform(quickFix);
			quickFix.setY(quickFix.y+yTrans);
			
			currMat.setTranslation(new Vector3f(quickFix));
			for(int i =0;i<16;i++){
				mat4[i] = currMat.getElement(i/4, i%4);
			}
			
			theWorkspaceModel.setTransformMatrix(currObj, mat4, MatrixOrder.ROW_MAJOR);
			
			
			theWorkspaceModel.getTransformMatrix(currObj, mat4, MatrixOrder.ROW_MAJOR);
			//Log.d("POW","Setting to the new Transform: " + Arrays.toString(mat4));
			
		}
		
		
		return true;
	}
	
	public void duplicateSTLObject(STLObject currPick){
		STLObject newObj = currPick.clone();
		theWorkspaceModel.addSTLObject(newObj);
		float[] result = new float[16];
		theWorkspaceModel.getTransformMatrix(currPick, result , MatrixOrder.COLUMN_MAJOR);
	
		this.theTransformHelper.setCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
		this.theTransformHelper.translateLeftRight((float)(Math.random()*25+25));//TODO better way to 
		this.theTransformHelper.translateBackForth((float)(Math.random()*25+25));//auto position
				
		this.theTransformHelper.getCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
				
		theWorkspaceModel.setTransformMatrix(newObj, result, MatrixOrder.COLUMN_MAJOR);
		
	}
	
	public void setScale(STLObject currPick, float scale){
		//TODO		
		float[] result = new float[16];
		theWorkspaceModel.getTransformMatrix(currPick, result , MatrixOrder.COLUMN_MAJOR);
		theTransformHelper.setCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
		theTransformHelper.setScale(scale);
		theTransformHelper.getCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
		theWorkspaceModel.setTransformMatrix(currPick, result, MatrixOrder.COLUMN_MAJOR);
		this.placeAllObjectsOnWorkspace();
	}
	
	public void increaseScale(STLObject currPick, float scale){
		float[] result = new float[16];
		theWorkspaceModel.getTransformMatrix(currPick, result , MatrixOrder.COLUMN_MAJOR);
		theTransformHelper.setCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
		float existingScale = theTransformHelper.getScale();
		theTransformHelper.setScale(existingScale + scale);
		theTransformHelper.getCurrentTransform(result, MatrixOrder.COLUMN_MAJOR);
		theWorkspaceModel.setTransformMatrix(currPick, result, MatrixOrder.COLUMN_MAJOR);
		this.placeAllObjectsOnWorkspace();
	}
	
	public void scaleToHeight(STLObject currPick){
		//TODO
	}
	
	public void removeSTLObject(STLObject currPick){
		this.theWorkspaceModel.removeSTLObject(currPick);
	}
	
	public void orientNextFace(STLObject currPick) {
		float[] result = new float[16];
		this.theWorkspaceModel.getTransformMatrix(currPick, result,MatrixOrder.ROW_MAJOR);	
		this.theTransformHelper.setCurrentTransform(result,MatrixOrder.ROW_MAJOR);
		float[] normal = new float[3];
		currPick.getNextUniqueNormal(normal);
		this.theTransformHelper.pointNormalDown(normal);
		
		float workspaceY, currMin;
		float[] mins = new float[3];
		theWorkspaceModel.getCurrMins(currPick, mins);
		STLWorkspaceObject currWS = theWorkspaceModel.getWorkspaceObject();
		if (currWS != null) {
			currMin = mins[1];
			workspaceY = currWS.getSurfaceY();
			this.theTransformHelper.placeOnWorkspace(workspaceY, currMin);
		}
		float[] newT = new float[16];
		this.theTransformHelper.getCurrentTransform(newT,MatrixOrder.ROW_MAJOR);
		this.theWorkspaceModel.setTransformMatrix(currPick, newT, MatrixOrder.ROW_MAJOR );		
	}

	public void resetCurrentModel(STLObject currPick) {
		float[] ident = new float[]{1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};	
		this.theWorkspaceModel.setTransformMatrix(currPick, ident, MatrixOrder.ROW_MAJOR);
	}
	

}
